// 版权所有2009 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包rand实现了不适合安全敏感工作的伪随机数生成器。
// 
// 随机数由源生成。顶级函数，如
// Float64和Int，使用默认的共享源代码，每次运行程序时生成确定性
// 值序列。如果每次运行需要不同的行为，请使用Seed函数初始化默认源。
// 默认源对于多个goroutine并发使用是安全的，但是
// 由NewSource创建的源不安全。
// 
// 此包的输出可能很容易预测，无论其种子是什么。有关适用于安全敏感工作的随机数，请参阅
// crypto/rand包。
package rand

import "sync"

// 源表示[0，1<<63]范围内均匀分布的
// 伪随机int64值的源。
type Source interface {
	Int63() int64
	Seed(seed int64)
}

// 源64也可以生成
// 
// 范围内均匀分布的伪随机uint64值[0，1<<64）直接。
// 如果Rand r的基础源s实现了Source64，
// 则r.Uint64返回一次调用s.Uint64的结果
// 而不是两次调用s.Int63。
type Source64 interface {
	Source
	Uint64() uint64
}

// NewSource返回一个带有给定值的新伪随机源。
// 不同于顶级函数使用的默认源，此源不适合多个goroutine并发使用。
func NewSource(seed int64) Source {
	var rng rngSource
	rng.Seed(seed)
	return &rng
}

// Rand是随机数源。
type Rand struct {
	src Source
	s64 Source64 // 如果src是source64 

	// readVal包含63位整数的剩余部分，用于字节
	// generati在最近一次读取调用期间打开。
	// 它被保存，以便下一次读取调用可以从上一次
	// 完成的位置开始。
	readVal int64
	// readPos表示readVal 
	// 的低位字节数仍然有效。
	readPos int8
}

// New返回使用src ABC中随机值的新RandDEFG
func New(src Source) *Rand {
	s64, _ := src.(Source64)
	return &Rand{src: src, s64: s64}
}

// Seed使用提供的Seed值将生成器初始化为确定性状态。
// Seed不应与任何其他Rand方法同时调用。
func (r *Rand) Seed(seed int64) {
	if lk, ok := r.src.(*lockedSource); ok {
		lk.seedPos(seed, &r.readPos)
		return
	}

	r.src.Seed(seed)
	r.readPos = 0
}

// Int63将非负伪随机63位整数作为int64返回。
func (r *Rand) Int63() int64 { return r.src.Int63() }

// Uint32以Uint32的形式返回伪随机32位值。
func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }

// Uint64以Uint64的形式返回伪随机64位值。
func (r *Rand) Uint64() uint64 {
	if r.s64 != nil {
		return r.s64.Uint64()
	}
	return uint64(r.Int63())>>31 | uint64(r.Int63())<<32
}

// Int31以int32的形式返回非负伪随机31位整数。
func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }

// Int Int返回非负伪随机Int。
func (r *Rand) Int() int {
	u := uint(r.Int63())
	return int(u << 1 >> 1) // 如果Int==int32 ABCDE，则清除符号位FG
}

// 如果n<=0，它会恐慌。
func (r *Rand) Int63n(n int64) int64 {
	if n <= 0 {
		panic("invalid argument to Int63n")
	}
	if n&(n-1) == 0 { // n是二的幂，可以掩盖
		return r.Int63() & (n - 1)
	}
	max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
	v := r.Int63()
	for v > max {
		v = r.Int63()
	}
	return v % n
}

// Int31n作为一个int32返回半开区间中的非负伪随机数[0，n）.如果n<=0，它会惊慌失措。n是二的幂，可以屏蔽
func (r *Rand) Int31n(n int32) int32 {
	if n <= 0 {
		panic("invalid argument to Int31n")
	}
		return r.Int31() & (n - 1)
	}
	max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
	v := r.Int31()
	for v > max {
		v = r.Int31()
	}
	return v % n
}

// int31n作为int32返回半开区间内的非负伪随机数[0，n）.
// n必须大于0，但int31n不检查此项；调用方必须确保它。
// int31n的存在是因为int31n效率低下，但Go 1兼容性
// 要求math/rand生成的值流保持不变。因此，
// int31n只能由n在内部使用全新引入的API.
// 
// 实现细节请参见：
// https:
// https:
func (r *Rand) int31n(n int32) int32 {
	v := r.Uint32()
	prod := uint64(v) * uint64(n)
	low := uint32(prod)
	if low < uint32(n) {
		thresh := uint32(-n) % uint32(n)
		for low < thresh {
			v = r.Uint32()
			prod = uint64(v) * uint64(n)
			low = uint32(prod)
		}
	}
	return int32(prod >> 32)
}

// Intn以int形式返回非负伪随机数在半开区间[0，n]中。
// 如果n<=0，它就会恐慌。
func (r *Rand) Intn(n int) int {
	if n <= 0 {
		panic("invalid argument to Intn")
	}
	if n <= 1<<31-1 {
		return int(r.Int31n(int32(n)))
	}
	return int(r.Int63n(int64(n)))
}

// Float64以Float64的形式返回半开区间[0.0,1.0]中的伪随机数。
func (r *Rand) Float64() float64 {
	// 更清晰、更简单的实现是：
	// 返回Float64（r.Int63n（1<<53））/（1<<53）
	// 但是，Go 1随
	// 返回float64（r.Int63（））/（1<<63）
	// 我们希望保留该价值流。
	// 
	// 价值流中有一个错误：r.Int63（）可能非常接近
	// 到1<<63，以至于部门凑整到1.0，我们保证
	// 结果始终小于1.0。
	// 
	// 我们试图通过将1.0映射回0.0来解决这一问题，但由于0附近的float64 
	// 值比1附近的值密度大得多，因此将1映射到0导致
	// 返回0的概率在理论上显著超调。
	// 相反，如果我们四舍五入到1，请再试一次。
	// 获取1只发生1/2⁵³的时间，所以大多数客户
	// 无论如何都不会遵守。
again:
	f := float64(r.Int63()) / (1 << 63)
	if f == 1 {
		goto again // 重新采样；此分支采用O（从不）
	}
	return f
}

// Float32以Float32形式返回半开区间[0.0,1.0]中的伪随机数。
func (r *Rand) Float32() float32 {
	// 与Float64中的原理相同：我们希望保留Go 1值
	// 流，但我们希望修复它，使其不返回1.0 
	// 这只会发生1/2⁴ 时间的百分比（加上1/2⁵在Float64中的时间的3）。
again:
	f := float32(r.Float64())
	if f == 1 {
		goto again // 重采样；此分支取O（非常罕见）
	}
	return f
}

// Perm返回半开区间[0，n]中整数的伪随机排列
// 在以下循环中，当i=0时的迭代总是将m[0]与m[0]交换.
func (r *Rand) Perm(n int) []int {
	m := make([]int, n)
	// 删除此无用迭代的更改是在init 
	// 语句中将1分配给i。但Perm也会影响r。进行此更改将影响
	// r的最终状态。因此，出于兼容性考虑，无法进行此更改
	// Go 1的原因。
	for i := 0; i < n; i++ {
		j := r.Intn(i + 1)
		m[i] = m[j]
		m[j] = i
	}
	return m
}

// Shuffle pseudo随机化元素的顺序。
// n是元素的数量。如果n<0，Shuffle会恐慌。
// swap使用索引i和j交换元素。
func (r *Rand) Shuffle(n int, swap func(i, j int)) {
	if n < 0 {
		panic("invalid argument to Shuffle")
	}

	// Fisher-Yates Shuffle:https:
	// Shuffle真的不应该用不适合32位的n调用。
	// 只需要很长的时间，但是有2种可能的排列，任何PRNG都不可能有足够大的内部状态来产生哪怕是很小的可能排列。尽管如此，正确的API签名接受int n，所以将其作为b处理尽我们所能。
	i := n - 1
	for ; i > 1<<31-1-1; i-- {
		j := int(r.Int63n(int64(i + 1)))
		swap(i, j)
	}
	for ; i > 0; i-- {
		j := int(r.int31n(int32(i + 1)))
		swap(i, j)
	}
}

// Read生成len（p）个随机字节并将它们写入p。它
// 始终返回len（p）和一个零错误。
// Read不应与任何其他Rand方法同时调用。
func (r *Rand) Read(p []byte) (n int, err error) {
	if lk, ok := r.src.(*lockedSource); ok {
		return lk.read(p, &r.readVal, &r.readPos)
	}
	return read(p, r.src, &r.readVal, &r.readPos)
}

func read(p []byte, src Source, readVal *int64, readPos *int8) (n int, err error) {
	pos := *readPos
	val := *readVal
	rng, _ := src.(*rngSource)
	for n = 0; n < len(p); n++ {
		if pos == 0 {
			if rng != nil {
				val = rng.Int63()
			} else {
				val = src.Int63()
			}
			pos = 7
		}
		p[n] = byte(val)
		val >>= 8
		pos--
	}
	*readPos = pos
	*readVal = val
	return
}

/*
 * Top-level convenience functions
 */

var globalRand = New(&lockedSource{src: NewSource(1).(*rngSource)})

// Type断言globalRand的源是一个锁定源，其src为*rngSource。
var _ *rngSource = globalRand.src.(*lockedSource).src

// Seed使用提供的Seed值将默认源初始化为
// 确定性状态。如果Seed is未调用，生成器的行为与
// 如果由Seed（1）进行种子设定.Seed值在
// 除以2/1时具有相同的余数，生成相同的伪随机序列。
// Seed与Rand.Seed方法不同，可以安全地并发使用。
func Seed(seed int64) { globalRand.Seed(seed) }

// Int63从默认源返回一个非负伪随机63位整数，作为int64 
// 的整数。
func Int63() int64 { return globalRand.Int63() }

// Uint32从默认源返回伪随机32位值作为Uint32 
// 。
func Uint32() uint32 { return globalRand.Uint32() }

// Uint64从默认源返回伪随机64位值作为Uint64 
// 。
func Uint64() uint64 { return globalRand.Uint64() }

// Int31从int32 
func Int31() int32 { return globalRand.Int31() }

// Int返回来自默认源的非负伪随机Int。
func Int() int { return globalRand.Int() }

// Int63n返回半开区间中的非负伪随机数，作为int64[0，n）
// 来自默认源。
// 如果n<=0，则会出现恐慌。
func Int63n(n int64) int64 { return globalRand.Int63n(n) }

// Int31n作为int32返回半开区间中的非负伪随机数[0，n）
// 来自默认源。
// 如果n<=0，则会出现恐慌。
func Int31n(n int32) int32 { return globalRand.Int31n(n) }

// Intn以int形式返回半开区间中的非负伪随机数[0，n）
// 来自默认源。
// 如果n<=0，它就会恐慌。
func Intn(n int) int { return globalRand.Intn(n) }

// Float64作为Float64返回半开区间[0.0,1.0]中的伪随机数
// 来自默认源。
func Float64() float64 { return globalRand.Float64() }

// Float32作为Float32返回半开区间中的伪随机数[0.0,1.0）
// 来自默认源。
func Float32() float32 { return globalRand.Float32() }

// Perm返回半开区间内整数
// 的伪随机排列，作为n个整数的一部分[0，n）来自默认源。
func Perm(n int) []int { return globalRand.Perm(n) }

// Shuffle伪随机使用默认源对元素的顺序进行随机化。
// n是元素的数量。如果n<0，Shuffle恐慌。
// swap使用索引i和j交换元素。
func Shuffle(n int, swap func(i, j int)) { globalRand.Shuffle(n, swap) }

// 读取从默认源生成len（p）个随机字节，
// 将它们写入p。它总是返回len（p）和nil错误。
// Read与Rand.Read方法不同，可以安全地并发使用。
func Read(p []byte) (n int, err error) { return globalRand.Read(p) }

// NormFloat64从默认源返回范围为
// [-math.MaxFloat64，+math.MaxFloat64]的正态分布浮点64，其中
// /标准正态分布（平均值=0，stddev=1）
// 。
// 若要生成不同的正态分布，调用方可以使用以下命令调整输出：
// 
// sample=NormFloat64（）*desiredStdDev+desiredMean 
// 
func NormFloat64() float64 { return globalRand.NormFloat64() }

// ExpFloat64返回范围内的指数分布的float64（0，+math.MaxFloat64]具有指数分布，其速率参数
// /（lambda）为1，其平均值为1/lambda（1）从默认的Source.
// 要生成具有不同速率参数的分发，调用方可以使用以下命令调整输出：
// 
// sample=ExpFloat64（）/DesiredRate参数
// 
func ExpFloat64() float64 { return globalRand.ExpFloat64() }

type lockedSource struct {
	lk  sync.Mutex
	src *rngSource
}

func (r *lockedSource) Int63() (n int64) {
	r.lk.Lock()
	n = r.src.Int63()
	r.lk.Unlock()
	return
}

func (r *lockedSource) Uint64() (n uint64) {
	r.lk.Lock()
	n = r.src.Uint64()
	r.lk.Unlock()
	return
}

func (r *lockedSource) Seed(seed int64) {
	r.lk.Lock()
	r.src.Seed(seed)
	r.lk.Unlock()
}

// seedPos为没有竞争条件的锁定源实现Seed。
func (r *lockedSource) seedPos(seed int64, readPos *int8) {
	r.lk.Lock()
	r.src.Seed(seed)
	*readPos = 0
	r.lk.Unlock()
}

// read为没有竞争条件的锁定源实现read。
func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
	r.lk.Lock()
	n, err = read(p, r.src, readVal, readPos)
	r.lk.Unlock()
	return
}
